#include "EString.h"
#include "DefineCommon.h"
#include <cstdio>
#include <stdio.h>

#ifdef linux
#include <string/pystring.h>
#endif

EString::EString(const char* str)
{
    if (str == NULL) 
    {
        const char* tempStr = "";
        m_size = m_capacity = strlen(tempStr);
        m_data = new char[m_capacity + 1];
        strcpy(m_data, tempStr);
        return;
    }

    m_size = m_capacity = strlen(str);
    m_data = new char[m_capacity + 1];
    strcpy(m_data, str);
}

EString::EString(const EString& s)		//使用对象初始化就变成拷贝构造了
{
    m_size = m_capacity = s.m_size;
    m_data = new char[m_capacity + 1];		//一定是深拷贝
    strcpy(m_data, s.m_data);
}
        
EString::~EString()
{
    delete[] m_data;
    m_size = m_capacity = 0;
}

const char* EString::data()
{
    return m_data;
}

const char* EString::data() const
{
    return m_data;
}

size_t EString::size()
{
    return m_size;
}

size_t EString::size() const
{
    return m_size;
}

void EString::reserve(size_t n)
{
    char* tmp = new char[n + 1];		//C++没有类似realloc的函数
    strcpy(tmp, m_data);		//所以统一使用异地扩容办法
    delete[] m_data;
    m_data = tmp;
    m_capacity = n;		//注意我们的_capacity描述的是不包括'\0'的容量
    //m_size = m_capacity;
}

//拷贝构造的现代写法
void EString::swap(EString& s)		//模拟实现了string类提供的swap接口
{
    std::swap(m_data, s.m_data);
    std::swap(m_size, s.m_size);
    std::swap(m_capacity, s.m_capacity);
}
        //
void EString::push_back(char ch)
{
    if (m_size == m_capacity)
    {
        size_t newcapacity = m_capacity == 0 ? 4 : m_capacity * 2;
        reserve(newcapacity);
    }
    m_data[m_size++] = ch;
    m_data[m_size] = '\0';		//对于尾插字符，我们需要手动放置'\0'
}

void EString::append(const char* str)
{
    if (m_size + strlen(str) > m_capacity)
    {
        reserve(m_size + strlen(str));		//开辟足够的空间
    }
    strcat(m_data, str);		//巧用函数
    m_size += strlen(str);		//不忘改变有效字符个数
}

void EString::append(const EString& str)
{
    this->append(str.m_data);
}

EString& EString::insert(size_t pos, char ch)
{
    if (m_size == m_capacity)
    {
        size_t newcapacity = m_capacity == 0 ? 4 : m_capacity * 2;
        reserve(newcapacity);
    }		//检查容量是否足够

    size_t end = m_size + 1;
    while (end > pos)
    {
        
        m_data[end] = m_data[end - 1];
        --end;
    }		//数据的挪动
    m_data[pos] = ch;
    m_size += 1;
    return *this;
}

EString& EString::insert(size_t pos, const char* str)
{
    if (m_size + strlen(str) > m_capacity)
    {
        reserve(m_size + strlen(str));
    }

    size_t end = m_size + strlen(str);
    while (end > pos)
    {
        m_data[end] = m_data[end - strlen(str)];
        --end;
    }
    strncpy(m_data + pos, str,strlen(str));
    //m_data += strlen(str);
    m_size += strlen(str);
    return *this;
}

EString& EString::erase(size_t pos , size_t len )
{
    assert(pos < m_size);
    if (len >= m_size - pos)
    {
        m_data[pos] = '\0';
        m_size -= len;
    }
    else
    {
        size_t end = pos + len;
        strcpy(m_data + pos, m_data + end);
        m_size -= len;
    }
    return *this;
}

void EString::replace(const char* subStrOld, const char* subStrNew)
{
#ifdef WIN32
    size_t lenOld = strlen(subStrOld);
    size_t lenNew = strlen(subStrNew);
    size_t posFindBegin = 0;
    size_t posOld = 0;

    // ELOG_DEBUG("---------------");
    // ELOG_DEBUG("lenOld=%d", lenOld);
    // ELOG_DEBUG("lenNew=%d", lenNew);

    while (posOld != -1)
    {
        posOld = this->find(subStrOld, posFindBegin);


        if(posOld == -1)
        {
            break;
        }

        this->erase(posOld, lenOld);
        this->insert(posOld, subStrNew);

        posFindBegin = posOld+lenNew;

        /*ELOG_DEBUG("posOld=%d,lenOld=%d,lenNew=%d,posFindBegin=%d"
                ,posOld
                ,lenOld
                ,lenNew
                ,posFindBegin);*/
    }

    // ELOG_DEBUG("---------------");
#endif

    
#ifdef linux
    std::string strThis(this->m_data);
    std::string strThisNew = pystring::replace(strThis, subStrOld, subStrNew);
    *this = EString::fromStdString(strThisNew);
#endif

}

void EString::replace(size_t pos, size_t len, const char* subStrNew)
{
    this->erase(pos, len);
    this->insert(pos, subStrNew);
}

void EString::remove(const char* subStr)
{
    size_t lenOld = strlen(subStr);
    size_t posFindBegin = 0;
    size_t posOld = 0;

    while (posOld != -1)
    {
        posOld = this->find(subStr, posFindBegin);

        if(posOld == -1)
        {
            break;
        }

        this->erase(posOld, lenOld);

        posFindBegin = posOld;
    }
}

void EString::removeLeft(size_t len)
{
    this->erase(0, len);
}

void EString::removeRight(size_t len)
{
    this->erase(m_size - len, len);
}

EString EString::subStr(size_t posBegin, size_t len) const
{
    if( 
        posBegin < 0
     || posBegin >= this->m_size
     || len <= 0
     || posBegin+len > this->m_size
     || this->m_size == 0
     )
    {
        ELOG_ERROR("posBegin or len is not correct");
        return EString();
    }

    char* tmp = new char[len+1];		//开辟空间
    char* ptrBegin = this->m_data+posBegin;
    strncpy(tmp, ptrBegin, len);
    tmp[len] = '\0';

    return EString(tmp);
}

EString EString::left(size_t len)
{
    return this->subStr(0, len);
}

EString EString::right(size_t len)
{
    return this->subStr(m_size-len, len);
}

EStringList EString::split(const EString& subStr) const
{
    EStringList strList;
    size_t len = subStr.size();
    size_t posFindBegin = 0;
    size_t pos = 0;

    while (pos != -1)
    {
        pos = this->find(subStr, posFindBegin);

        if(pos == -1 )
        {
            if(posFindBegin >= m_size)
                break;
            else
                pos = m_size;
        }

        strList.push_back(
                this->subStr(posFindBegin, pos-posFindBegin)
                );

        posFindBegin = pos+len;
    }
    
    if(strList.size() == 0)
    {
        strList.push_back(*this);
    }
    return strList;
}

int EString::find(char ch, size_t pos) const		//pos是查找的起始位置
{
    assert(pos < m_size);
    while (pos < m_size)
    {
        if (m_data[pos] == ch)
        {
            return pos;
        }
        pos++;
    }
    return -1;
}

int EString::find(const char* str, size_t pos) const
{
    if (pos >= m_size)
        return -1;
    char* ret = strstr(m_data+pos, str);		//注意开始查找的位置
    if (ret == nullptr)
    {
        return -1;
    }
    else
    {
        return ret - m_data;		//指针相减等于元素个数
    }
}

int EString::find(const EString& s, size_t pos) const
{
    // assert(pos < m_size);
    char* tmp = strstr(m_data+pos, s.m_data);		//注意开始查找的位置
    if (tmp == nullptr)
    {
        return -1;
    }
    else
    {
        return tmp - m_data;
    }
}

bool EString::contains(const char* subStr) const
{
    if(this->find(subStr) != -1)
    {
        return true;
    }
    
    return false;
}

bool EString::contains(const EString& subStr) const
{
    if(this->find(subStr) != -1)
    {
        return true;
    }
    
    return false;
}

bool EString::isEmpty() const
{
    //TODO
    return this->size() == 0;
}

//赋值运算符重载的现代写法
// EString& EString::operator=(EString s)		//使用传值调用，s就是一个临时对象
// {
    // swap(s);		//交换,这里的swap等同与拷贝构造的swap
    // return *this;
// }

EString& EString::operator=(const EString& s)
{
    if (this != &s)		//确保不是自我赋值
    {
        char* tmp = new char[s.m_capacity + 1];		//开辟空间
        strcpy(tmp, s.m_data);		//拷贝字符串

        delete[] m_data;		//改变_str,指向新的空间
        m_data = tmp;

        m_size = s.m_size;
        m_capacity = s.m_capacity;
    }
    return *this;
}

EString& EString::operator+=(const char* str)
{
    append(str);
    return *this;
}

EString& EString::operator+=(const EString& str)
{
    append(str);
    return *this;
}

EString& EString::operator+=(char ch)		//重载
{
    push_back(ch);
    return *this;
}

EString EString::operator+(const char* str) const
{
    EString newStr(*this);

    newStr.append(str);

    return newStr;
}

EString EString::operator+(const char* str)
{
    EString newStr(*this);

    newStr.append(str);

    return newStr;
}

EString EString::operator+(const EString& s)
{
    EString newStr(*this);

    newStr.append(s);

    return newStr;
}

EString EString::operator+(char ch)
{
    EString newStr(*this);

    newStr.push_back(ch);

    return newStr;
}

char& EString::operator[](size_t pos)		
{
    return m_data[pos];
}

char& EString::operator[](size_t pos) const		//需要兼顾const 修饰的对象
{
    return m_data[pos];
}

int EString::compare(const EString& str) const
{
    int result = -1;

    for(int i = 0 ; i < m_size && i < str.m_size; i++)
    {
        if(m_data[i] < str.m_data[i])
        {
            result = -1;
            break;
        }
        else if(m_data[i] > str.m_data[i])
        {
            result = 1;
            break;
        }
        else 
        {
            result = 0;
        }
    }

    if(result == 0 && m_size > str.m_size)
    {
        result = 1;
    }
    else if(result == 0 && m_size < str.m_size)
    {
        result = -1;
    }

    return result;
}

bool EString::operator<(const EString& str) const
{
    int result = this->compare(str);

    if(result == -1)
    {
        return true;
    }

    return false;

    // bool result = false;
    // for(int i = 0 ; i < m_size && i < str.m_size; i++)
    // {
        // if(m_data[i] < str.m_data[i])
        // {
            // result = true;
            // break;
        // }
        // else if(m_data[i] > str.m_data[i])
        // {
            // result = false;
            // break;
        // }
    // }
    // return result;
}

bool EString::operator>(const EString& str) const
{
    int result = this->compare(str);

    if(result == 1)
    {
        return true;
    }

    return false;
}

bool EString::operator==(const EString& str) const
{
    int result = this->compare(str);

    if(result == 0)
    {
        return true;
    }

    return false;
}

bool EString::operator!=(const EString& str) const
{
    int result = this->compare(str);

    if (result == 0)
    {
        return false;
    }

    return true;
}

// bool EString::operator==(const char* str)
// {
    // int result = this->compare(str);

    // if(result == -1)
    // {
        // return true;
    // }

    // return false;
    // return true;
// }

// bool EString::operator==(const char* str) const
// {
    // //TODO
    // return true;
// }


EString EString::number(int value)
{
    char* data = new char[21];
    sprintf(data, "%d", value);

    EString str(data); 

    delete [] data;
    
    return str;
}

EString EString::number(size_t value)
{
    char* data = new char[21];
    sprintf(data, "%d", (int)value);

    EString str(data); 

    delete [] data;
    
    return str;
}

EString EString::number(double value, const char* formatStr)
{
    char* data = new char[21];
    sprintf(data, formatStr, value);

    EString str(data); 

    delete [] data;
    
    return str;
}

EString EString::boolValue(bool value)
{
    if(value == true)
    {
        return EString("true");
    }
    else
    {
        return EString("false");
    }
}

bool EString::EStringListContains(const EStringList& list, const EString& str)
{
    for(int i = 0 ; i < list.size(); i++)
    {
        if(list[i] == str)
        {
            return true;
        }
    }

    return false;

}

EString EString::fromStdString(const std::string& stdStr)
{
    EString str(stdStr.data());
    return str;
}

EString EString::EStringListGetPrintStr(const EStringList& strList)
{
    EString temp;
    temp = EString("EStringList.size=") + EString::number(strList.size()) + "\n";

    for(int i = 0 ; i < strList.size(); i++)
    {
       temp += strList[i] + "\n"; 
    }

    return temp;
}
// friend std::ostream& operator<<(std::ostream& out, const string& s)
// {
    // out << s._str;
    // return out;
// }

        //成员函数
        // typedef char* iterator;

        // iterator begin()
        // {
            // return _str;		//数组名就是首元素地址
        // }
        // iterator end()
        // {
            // return _str + _size;		//指向最后一个元素的下一个位置，即'\0'
        // }
        // iterator begin() const
        // {
            // return _str;		
        // }
        // iterator end() const
        // {
            // return _str + _size;		
        // }


        // string(const string& s)
        // :_str(nullptr)
        // ,_size(0)
        // ,_capacity(0)
        // {
        // string tmp(s._str);		//先使用一个临时对象构造
        // swap(tmp);		//然后交换内容
        // //this->swap(tmp);		//与上面等同的swap调用
        // }


        // friend std::ostream& operator<<(std::ostream& out, const string& s)
        // {
        // out << s._str;
        // return out;
        // }




